home *** CD-ROM | disk | FTP | other *** search
- #include "global.h"
- #include <ctype.h>
-
- /* Given a working directory and an arbitrary pathname, resolve them into
- * an absolute pathname. Memory is allocated for the result, which
- * the caller must free
- */
- char *
- pathname(cd,path)
- char *cd; /* Current working directory */
- char *path; /* Pathname argument */
- {
- register char *buf,*cp;
- char *cdtmp,*pathtmp,*strcpy();
-
- if(cd == NULLCHAR || path == NULLCHAR)
- return NULLCHAR;
-
- #if (defined(MSDOS) || defined(ATARI_ST))
- /* Make temporary copies of cd and path
- * with all \'s translated to /'s
- */
- if ((pathtmp = malloc((unsigned)strlen(path)+1)) == NULLCHAR)
- return NULLCHAR;
- for (cp = path = strcpy(pathtmp,path); *cp != '\0'; cp++)
- if (*cp == '\\')
- *cp = '/';
-
- if ((cdtmp = malloc((unsigned)strlen(cd)+1)) == NULLCHAR) {
- free(pathtmp);
- return NULLCHAR;
- }
- for (cp = cd = strcpy(cdtmp,cd); *cp != '\0'; cp++)
- if (*cp == '\\')
- *cp = '/';
- #endif
-
- /* Strip any leading white space on args */
- while(*cd == ' ' || *cd == '\t')
- cd++;
- while(*path == ' ' || *path == '\t')
- path++;
-
- /* Allocate and initialize output buffer; user must free */
- buf = malloc((unsigned)strlen(cd) + strlen(path) + 10); /* fudge factor */
- if (buf == NULLCHAR)
- goto nomem;
- buf[0] = '\0';
-
- /* Interpret path relative to cd only if it doesn't begin with "/" */
- /* or "D:/" (support for drive names) */
- if(path[0] == '/' && cd[1] == ':') {
- buf[0] = cd[0]; /* start from root on current drv */
- buf[1] = ':';
- buf[2] = '\0';
- }
- if(path[0] != '/' &&
- !(isalpha(path[0]) && path[1] == ':' && path[2] == '/'))
- crunch(buf,cd);
-
- crunch(buf,path);
-
- /* Special case: null final path or drive only means the root directory */
- if(buf[0] == '\0' ||
- (isalpha(buf[0]) && buf[1] == ':' && buf[2] == '\0'))
- strcat(buf,"/");
-
- nomem:
- #if (defined(MSDOS) || defined(ATARI_ST))
- /* Translate all /'s back to \'s and free temp copies of args */
- for (cp = buf; *cp != '\0'; cp++)
- if (*cp == '/')
- *cp = '\\';
- free(cdtmp);
- free(pathtmp);
- #endif
- return buf;
- }
-
- /* Process a path name string, starting with and adding to
- * the existing buffer
- */
- static
- crunch(buf,path)
- char *buf;
- register char *path;
- {
- register char *cp;
-
- if (isalpha(*path) && path[1] == ':'){ /* drive spec */
- cp = buf; /* Re-write entire buffer */
- *cp++ = *path++;
- *cp++ = *path++;
- *cp = '\0';
- } else {
- cp = buf + strlen(buf); /* Start write at end of current buffer */
- }
-
- /* Now start crunching the pathname argument */
- for(;;){
- /* Strip leading /'s; one will be written later */
- while(*path == '/')
- path++;
- if(*path == '\0')
- break; /* no more, all done */
- /* Look for parent directory references, either at the end
- * of the path or imbedded in it
- */
- if(strcmp(path,"..") == 0 || strncmp(path,"../",3) == 0){
- /* Hop up a level */
- if((cp = rindex(buf,'/')) == NULLCHAR)
- cp = buf; /* Don't back up beyond root */
- *cp = '\0'; /* In case there's another .. */
- path += 2; /* Skip ".." */
- while(*path == '/') /* Skip one or more slashes */
- path++;
- /* Look for current directory references, either at the end
- * of the path or imbedded in it
- */
- } else if(strcmp(path,".") == 0 || strncmp(path,"./",2) == 0){
- /* "no op" */
- path++; /* Skip "." */
- while(*path == '/') /* Skip one or more slashes */
- path++;
- } else {
- /* Ordinary name, copy up to next '/' or end of path */
- *cp++ = '/';
- while(*path != '/' && *path != '\0')
- *cp++ = *path++;
- }
- }
- *cp++ = '\0';
- }
-